<template>
  <div class="video-list-container">
    <!-- 视频列表 -->
    <div class="videos-grid">
      <div
        class="video-container video-card"
        v-for="video in displayVideos"
        :key="video.id"
        @click="jumpToVideoDetail(video)"
      >
        <div class="thumbnail-container">
          <img :src="video.thumbnail" class="thumbnail" alt="" />
          <div class="video-stats">
            <div class="stat-item">
              <img src="@/assets/icons/播放.svg" alt="" />
              {{ formatCount(video.viewCount) }}
            </div>
            <div class="stat-item">
              <img src="@/assets/icons/弹幕.svg" alt="" />
              {{ formatCount(video.danmuCount) }}
            </div>
          </div>
          <div class="video-duration">
            {{ formatDuration(video.duration) }}
          </div>
        </div>
        <div class="video-details">
          <span
            class="video-title"
            v-html="highlightKeyword(video.title)"
          ></span>
          <div class="up-info">
            <img
              src="@/assets/icons/UP主_32.svg"
              alt="UP主头像"
              class="up-avatar"
            />
            <span class="up-name">{{ video.author }}</span>
            <span class="up-name">·</span>
            <span class="video-time">{{ video.createTime }}</span>
          </div>
          <!-- 添加标签显示 -->
          <div class="video-tags" v-if="video.tags && video.tags.length">
            <span class="tag" v-for="(tag, index) in video.tags" :key="index">
              {{ tag }}
            </span>
          </div>
        </div>
      </div>
    </div>

    <!-- 加载更多提示 -->
    <div
      class="loading-container"
      ref="loadingRef"
      v-if="!noMoreData && !showNoMoreTip"
    >
      <div class="loading-spinner" v-if="isLoading"></div>
      <span v-if="isLoading">正在加载更多视频...</span>
    </div>

    <!-- 没有更多数据提示 -->
    <div class="no-more" v-if="noMoreData || showNoMoreTip">
      — 没有更多内容啦 —
    </div>
  </div>
</template>

<script setup lang="ts">
import { inject, onMounted, onUnmounted, ref, computed, watchEffect } from 'vue'
import { useRouter } from 'vue-router'

// 导入所有16张图片资源
import banner1 from '@/assets/anime/images/banner1.png'
import banner2 from '@/assets/anime/images/banner2.png'
import banner3 from '@/assets/anime/images/banner3.png'
import banner4 from '@/assets/anime/images/banner4.png'
import banner5 from '@/assets/anime/images/banner5.png'
import banner6 from '@/assets/anime/images/banner6.png'
import banner7 from '@/assets/anime/images/banner7.png'
import banner8 from '@/assets/anime/images/banner8.png'
import banner9 from '@/assets/anime/images/banner9.png'
import banner10 from '@/assets/anime/images/banner10.png'
import banner11 from '@/assets/anime/images/banner11.png'
import banner12 from '@/assets/anime/images/banner12.png'
import banner13 from '@/assets/anime/images/banner13.png'
import banner14 from '@/assets/anime/images/banner14.png'
import banner15 from '@/assets/anime/images/banner15.png'
import banner16 from '@/assets/anime/images/banner16.png'

// 将所有banner放入数组方便随机选择
const bannerImages = [
  banner1,
  banner2,
  banner3,
  banner4,
  banner5,
  banner6,
  banner7,
  banner8,
  banner9,
  banner10,
  banner11,
  banner12,
  banner13,
  banner14,
  banner15,
  banner16,
]

// 定义属性
const props = defineProps({
  videos: {
    type: Array,
    default: () => [],
  },
  loading: {
    type: Boolean,
    default: false,
  },
  noMore: {
    type: Boolean,
    default: false,
  },
  highlightKeyword: {
    type: String,
    default: '',
  },
  userId: {
    type: [String, Number],
    default: null,
  },
})

// 视频接口定义
interface Video {
  id: number | string
  title: string
  thumbnail: string
  duration: number // 视频时长（秒）
  viewCount: number
  danmuCount: number
  author: string
  authorAvatar?: string
  createTime: string
  tags?: string[]
}

// 二次元相关标题
const animeTitles = [
  '《进击的巨人》最终季原声带完整收录，震撼人心的配乐集',
  '《鬼灭之刃》刀匠村篇最新情报，炭治郎将锻造新武器',
  '《间谍过家家》第二季最新剧情解析，安妮亚的超能力揭秘',
  '《咒术回战》五条悟的领域展开技术详解与角色分析',
  '《chain saw man》动画化决定，最新PV公开让粉丝沸腾',
  '2024年春季新番导视，不容错过的十大热门动画',
  '《海贼王》漫画最新剧情：路飞的新形态与最终之岛的秘密',
  '宫崎骏电影《千与千寻》隐藏细节与创作背景深度解析',
  '《约定的梦幻岛》第二季制作幕后故事，原作者参与剧本创作',
  '《86-不存在的战区-》续作决定，最新视觉图公开',
  '《铃芽之旅》新海诚导演访谈：创作灵感与动画技术突破',
  '《SPY×FAMILY》最新角色设计图公开，新角色即将登场',
  '《冰海战记》第二季前瞻，维京传奇的史诗续篇',
  '《EVA新剧场版》终章解析，庵野秀明的告别与新起点',
  '《鲁路修》15周年纪念活动公开，全新动画企划启动',
  '《赛博朋克：边缘行者》动画音乐全解析，如何打造未来都市氛围',
  '《来自深渊》电影最新预告，原创剧情引发热议',
  '《刀剑神域进击篇》情报解禁，桐人将在虚拟世界再次冒险',
  '《辉夜大小姐》最终季制作决定，石上会告白成功吗',
  '《overlord》第五季制作确认，安兹乌尔恭将征服新大陆',
  '《钢之炼金术师》20周年纪念活动，粉丝最怀念的经典场景盘点',
  '《文豪野犬》最新剧情：太宰治的过去与组织的黑暗秘密',
  '《魔法少女小圆》新作企划公开，虚渊玄再执笔',
  '《紫罗兰永恒花园》外传小说动画化，新角色声优阵容公开',
  '《进击的巨人》作者谏山创新作前瞻，离开巨人世界后的新尝试',
  '《龙珠超》漫画最新话：悟空与贝吉塔的新形态展示',
  '《JOJO的奇妙冒险》第九部前瞻，荒木飞吕彦的新世界',
  '《鬼灭之刃》柱训练篇动画化决定，制作阵容公开',
  '《物语系列》新作动画确认，西尾维新的奇妙世界再次展开',
  '《排球少年》最终话解析，日本高中排球的青春传奇',
]

// 二次元相关UP主
const animeUploaders = [
  '动漫研究社',
  '新番时间表',
  '翻译君字幕组',
  '动画笔记',
  '二次元领域',
  '漫评家小佐',
  '声优情报站',
  '动漫原画师',
  '日本文化研究所',
  '萌系画师协会',
  '动画音乐鉴赏',
  '京都动画粉丝会',
  'EVA研究委员会',
  '宫崎骏作品赏析',
  '物语系列研究会',
  '巨人考察团',
  '动漫周边测评',
  'MAD大师工作室',
  '二次元音乐电台',
  '漫改文化研究',
]

// 二次元相关标签
const animeTags = [
  '动画',
  '漫画',
  '轻小说',
  'COSPLAY',
  '声优',
  '日漫',
  '国漫',
  '动画音乐',
  '角色歌',
  '同人创作',
  'AMV',
  'MAD',
  '热门新番',
  '经典动画',
  '动画电影',
  '催泪',
  '治愈',
  '热血',
  '机战',
  '奇幻',
  '冒险',
  '青春',
  '恋爱',
  '悬疑',
  '校园',
  '日常',
  '魔法少女',
  '异世界',
  '京阿尼',
  'trigger',
  '霸权',
  '萌豚',
  '热门角色',
  '圣地巡礼',
  '手办',
  '模型',
  '画师',
  '声优',
]

const router = useRouter()
const loadingRef = ref<HTMLElement | null>(null)

// 本地状态
const localVideos = ref<Video[]>([])
const currentPage = ref(1)
const localLoading = ref(false)
const localNoMore = ref(false)
const showNoMoreTip = ref(false)

// 注入分类数据（如果在分类页面中使用）
const categoryData = inject('categoryData', {
  categoryId: ref(''),
  subCategoryId: ref(undefined),
})

// 计算最终显示的视频列表
const displayVideos = computed(() => {
  // 优先使用传入的视频数据
  if (props.videos && props.videos.length > 0) {
    return props.videos
  }
  // 如果没有传入视频数据，则使用本地生成的数据
  return localVideos.value
})

// 计算最终的加载状态
const isLoading = computed(() => {
  return props.loading || localLoading.value
})

// 计算最终的"没有更多"状态
const noMoreData = computed(() => {
  return props.noMore || localNoMore.value
})

// 获取随机的二次元图片
const getRandomBanner = () => {
  return bannerImages[Math.floor(Math.random() * bannerImages.length)]
}

// 获取随机的二次元标题
const getRandomAnimeTitle = () => {
  return animeTitles[Math.floor(Math.random() * animeTitles.length)]
}

// 获取随机的UP主名称
const getRandomUploader = () => {
  return animeUploaders[Math.floor(Math.random() * animeUploaders.length)]
}

// 获取2-4个随机标签
const getRandomTags = () => {
  const tags = [...animeTags]
  const shuffled = tags.sort(() => 0.5 - Math.random())
  return shuffled.slice(0, Math.floor(Math.random() * 3) + 2)
}

// 生成模拟视频数据
const generateMockVideos = (page: number, pageSize: number = 10) => {
  const mockVideos: Video[] = []
  const startIndex = (page - 1) * pageSize

  for (let i = 0; i < pageSize; i++) {
    const id = startIndex + i + 1
    const creationDate = new Date()
    creationDate.setDate(
      creationDate.getDate() - Math.floor(Math.random() * 30),
    )

    mockVideos.push({
      id: id,
      title: getRandomAnimeTitle(),
      thumbnail: getRandomBanner(),
      duration: Math.floor(Math.random() * 600) + 60, // 1-11分钟
      viewCount: Math.floor(Math.random() * 1000000) + 1000,
      danmuCount: Math.floor(Math.random() * 50000) + 100,
      author: getRandomUploader(),
      createTime: formatDate(creationDate),
      tags: getRandomTags(),
    })
  }

  return mockVideos
}

// 加载本地模拟数据
const loadLocalMockData = async () => {
  if (localLoading.value || localNoMore.value) return

  localLoading.value = true

  try {
    // 模拟网络延迟
    await new Promise((resolve) => setTimeout(resolve, 800))

    // 生成新的模拟数据
    const newVideos = generateMockVideos(currentPage.value)
    localVideos.value = [...localVideos.value, ...newVideos]

    // 页码加1
    currentPage.value++

    // 模拟数据到达上限
    if (currentPage.value > 4) {
      localNoMore.value = true
    }
  } finally {
    localLoading.value = false
  }
}

// 格式化数字（例如：1.2万）
const formatCount = (count: number): string => {
  if (!count && count !== 0) return '-'
  if (count === 0) return '-'

  if (count < 10000) {
    return count.toString()
  } else if (count < 100000000) {
    return (count / 10000).toFixed(1) + '万'
  } else {
    return (count / 100000000).toFixed(1) + '亿'
  }
}

// 格式化视频时长（例如：05:30）
const formatDuration = (seconds: number): string => {
  if (!seconds) return '00:00'

  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = Math.floor(seconds % 60)

  const formattedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`
  const formattedSeconds =
    remainingSeconds < 10 ? `0${remainingSeconds}` : `${remainingSeconds}`

  return `${formattedMinutes}:${formattedSeconds}`
}

// 格式化日期
const formatDate = (date: Date): string => {
  const now = new Date()
  const diff = now.getTime() - date.getTime()

  // 小于一天，显示x小时前
  if (diff < 86400000) {
    const hours = Math.floor(diff / 3600000)
    return hours > 0 ? `${hours}小时前` : '刚刚'
  }

  // 小于一个月，显示x天前
  if (diff < 2592000000) {
    return `${Math.floor(diff / 86400000)}天前`
  }

  // 否则显示具体日期
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

// 高亮关键词
const highlightKeyword = (text: string): string => {
  if (!props.highlightKeyword) return text

  const keyword = props.highlightKeyword.trim()
  if (!keyword) return text

  const regex = new RegExp(`(${keyword})`, 'gi')
  return text.replace(regex, '<span class="keyword-highlight">$1</span>')
}

// 跳转到视频详情页
const jumpToVideoDetail = (video: Video) => {
  router.push(`/video/detail/${video.id}`)
}

// 设置无限滚动观察器
const setupInfiniteScroll = () => {
  const observer = new IntersectionObserver(
    (entries) => {
      if (entries[0].isIntersecting) {
        if (props.videos.length > 0) {
          // 如果使用的是外部传入的视频数据，触发外部加载更多事件
          if (!props.loading && !props.noMore) {
            emit('loadMore')
          }
        } else {
          // 如果使用的是内部生成的数据，加载更多本地数据
          if (!localLoading.value && !localNoMore.value) {
            loadLocalMockData()
          }
        }
      }
    },
    {
      root: null,
      rootMargin: '0px 0px 200px 0px', // 提前200px加载
      threshold: 0.1,
    },
  )

  if (loadingRef.value) {
    observer.observe(loadingRef.value)
  }

  // 保存观察器引用以便在组件卸载时清除
  return observer
}

// 定义事件
const emit = defineEmits(['loadMore'])

// 针对有限视频列表的处理
watchEffect(() => {
  if (props.videos && props.videos.length > 0 && props.noMore) {
    showNoMoreTip.value = true
  } else {
    showNoMoreTip.value = false
  }
})

// 初始化
let observer: IntersectionObserver | null = null

onMounted(() => {
  // 如果没有传入视频数据，则加载本地模拟数据
  if (props.videos.length === 0 && localVideos.value.length === 0) {
    loadLocalMockData()
  }

  // 延迟设置观察器，确保DOM已加载
  setTimeout(() => {
    observer = setupInfiniteScroll()
  }, 100)

  // 为视频卡片添加动画
  setTimeout(() => {
    const cards = document.querySelectorAll('.video-card')
    cards.forEach((card, index) => {
      setTimeout(() => {
        card.classList.add('animate-in')
      }, index * 100) // 每个卡片延迟100ms显示，创建瀑布流效果
    })
  }, 200)
})

onUnmounted(() => {
  // 清除观察器
  if (observer) {
    observer.disconnect()
  }
})
</script>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'VideoList',
})
</script>

<style scoped lang="scss">
.video-list-container {
  padding: 20px 0;
  width: 100%;
}

.videos-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;

  @media (max-width: 1200px) {
    grid-template-columns: repeat(4, 1fr);
  }

  @media (max-width: 992px) {
    grid-template-columns: repeat(3, 1fr);
  }

  @media (max-width: 768px) {
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }

  @media (max-width: 480px) {
    grid-template-columns: 1fr;
  }
}

.video-container {
  cursor: pointer;
  transition: all 0.3s ease;
  border-radius: 12px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.8);
  box-shadow: 0 4px 12px rgba(254, 78, 164, 0.15);

  &:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(254, 78, 164, 0.25);

    .thumbnail {
      transform: scale(1.08);
    }

    .video-title {
      color: #fe4ea4;
    }
  }
}

.thumbnail-container {
  position: relative;
  width: 100%;
  height: 0;
  padding-bottom: 56.25%;
  /* 16:9 宽高比 */
  overflow: hidden;
  border-radius: 12px 12px 0 0;

  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(
      45deg,
      rgba(254, 78, 164, 0.2),
      rgba(255, 214, 255, 0.1)
    );
    pointer-events: none;
    mix-blend-mode: overlay;
  }
}

.thumbnail {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}

.video-stats {
  position: absolute;
  bottom: 8px;
  left: 8px;
  display: flex;
  gap: 10px;
  color: white;
  font-size: 12px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
  z-index: 2;

  .stat-item {
    display: flex;
    align-items: center;
    gap: 4px;
    background: rgba(0, 0, 0, 0.5);
    padding: 2px 6px;
    border-radius: 12px;
    backdrop-filter: blur(4px);

    img {
      width: 14px;
      height: 14px;
      filter: brightness(10);
    }
  }
}

.video-duration {
  position: absolute;
  bottom: 8px;
  right: 8px;
  background-color: rgba(0, 0, 0, 0.6);
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  color: white;
  backdrop-filter: blur(4px);
  z-index: 2;
}

.video-details {
  padding: 12px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;

  .video-title {
    display: block;
    font-size: 14px;
    font-weight: 500;
    margin-bottom: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.4;
    height: 2.8em; // 确保两行高度固定
    transition: color 0.3s ease;
    color: #333;

    :deep(.keyword-highlight) {
      color: #fe4ea4;
      font-weight: bold;
    }
  }

  .up-info {
    display: flex;
    align-items: center;
    font-size: 12px;
    color: #666;
    margin-bottom: 8px;

    .up-avatar {
      width: 18px;
      height: 18px;
      border-radius: 50%;
      margin-right: 4px;
      object-fit: cover;
    }

    .up-name {
      margin-right: 4px;
      transition: color 0.3s;

      &:hover {
        color: #fe4ea4;
      }
    }

    .video-time {
      margin-left: 4px;
      color: #999;
    }
  }

  .video-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;

    .tag {
      font-size: 10px;
      color: #fe4ea4;
      background-color: rgba(254, 78, 164, 0.1);
      padding: 2px 6px;
      border-radius: 10px;
      transition: all 0.3s;

      &:hover {
        background-color: rgba(254, 78, 164, 0.2);
        transform: translateY(-2px);
      }
    }
  }
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 30px 0;
  color: #666;

  .loading-spinner {
    width: 22px;
    height: 22px;
    border: 3px solid #fe4ea4;
    border-radius: 50%;
    border-top-color: transparent;
    margin-right: 10px;
    animation: spin 0.8s linear infinite;
  }
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

.no-more {
  text-align: center;
  padding: 20px 0;
  color: #999;
  font-size: 14px;
  font-style: italic;
}

/* 为卡片添加动画效果 */
.video-card {
  opacity: 1;
  transform: translateY(0);
}

.animate-in {
  animation: fadeInUp 0.6s forwards;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
